<template>
  <div class="sign-in">
    <img
      src="@/assets/images/logo.png"
      width="118"
      height="24"
      alt=""
      class="mt-6 ml-8" />
    <a-form
      ref="formRef"
      :model="formState"
      :rules="rules"
      layout="vertical"
      class="sign-form">
      <h1 class="text-20px font-bold leading-7 m-0 mb-12 text-center">
        欢迎登录Hyper CDN
      </h1>
      <a-form-item
        class="mb-4!"
        hide-label
        :help="accountError"
        :validate-status="accountError ? 'error' : undefined">
        <a-input
          v-model="formState.account"
          placeholder="请输入账号"
          size="large"
          @change="accountError = ''"></a-input>
      </a-form-item>
      <a-form-item hide-label>
        <a-input-password
          v-model="formState.password"
          placeholder="请输入密码"
          size="large"
          @change="accountError = ''"
          @keyup.enter="handleSubmit"></a-input-password>
      </a-form-item>
      <a-button
        type="primary"
        size="large"
        :disabled="isDisabled"
        :loading="loading"
        @click="handleSubmit"
        >登录</a-button
      >
    </a-form>
    <visual-shield
      ref="visualShieldRef"
      :request="behavioralCaptcha"
      :verify="handleVerify"></visual-shield>
  </div>
</template>
<script lang="ts" setup>
import { ResultEnum } from '@/apis/http'
import {
  getApiCaptchaImageApi,
  getCaptchaPreCheckApi,
  postApiCaptchaVerifyApi,
  postApiLoginApi
} from '@/apis/modules/auth'
import {
  useBehavioralCaptcha,
  type RequestFnOptions,
  type VerifyOptions,
  type VisualShieldInstance
} from '@/components/visual-shield'
import { useAppStore } from '@/stores/app'
import type { FieldRule, FormInstance } from '@arco-design/web-vue'
const visualShieldRef = ref<VisualShieldInstance>()
const formRef = ref<FormInstance>()

const router = useRouter()
const appStore = useAppStore()
const loading = ref(false)
const behavioralCaptchaKey = ref('')
const accountError = ref<string>('')
const formState = reactive({
  account: '',
  password: ''
})
const rules: Record<string, FieldRule[]> = {
  account: [
    {
      required: true,
      message: '请输入账号'
    }
  ],
  password: [
    {
      required: true,
      message: '请输入密码'
    }
  ]
}
const isDisabled = computed<boolean>(
  () => !formState.password || !formState.account || loading.value
)
const handleLogin = () => {
  loading.value = true
  const data = {
    account: formState.account,
    captcha_key: behavioralCaptchaKey.value,
    password: formState.password
  }
  postApiLoginApi(data)
    .then((res) => {
      if (res.code === ResultEnum.SUCCESS) {
        appStore.token = res.data.token
        accountError.value = ''
        router.replace('/')
      } else if (res.code === ResultEnum.WRONGPASSWORD) {
        accountError.value = res.message ?? '账号或密码不正确,请重试'
      }
    })
    .finally(() => {
      loading.value = false
    })
}
const { withInterceptor } = useBehavioralCaptcha(visualShieldRef, handleLogin)

// 生成行为验证码
const behavioralCaptcha = ({
  loading,
  onSuccess,
  onError,
  onFrequent
}: RequestFnOptions) => {
  loading.value = true
  getApiCaptchaImageApi()
    .then((res) => {
      if (Number(res.code) === ResultEnum.SUCCESS) {
        const { image_base64, thumb_base64, key } = Object.assign(
          { image_base64: '', thumb_base64: '', key: '' },
          res.data
        )
        onSuccess(image_base64, thumb_base64)
        behavioralCaptchaKey.value = key
      } else if (Number(res.code) === ResultEnum.FREQUENTREQUEST) {
        onFrequent(res?.message)
        const { key } = Object.assign(
          { image_base64: '', thumb_base64: '', key: '' },
          res.data
        )
        behavioralCaptchaKey.value = key
      } else {
        onError(res.message)
      }
    })
    .finally(() => {
      loading.value = false
    })
}

// 验证验证码
const handleVerify = ({ onError, onSuccess, points }: VerifyOptions) => {
  postApiCaptchaVerifyApi({
    key: behavioralCaptchaKey.value,
    dots: String(points)
  }).then((res: any) => {
    if (Number(res.code) === 2000) {
      onSuccess()
    } else {
      onError(res.message)
    }
  })
}

const handleSubmit = async () => {
  if (isDisabled.value) return
  getCaptchaPreCheckApi({})
    .then((res) => {
      const needCaptcha = res.need_captcha
      if (needCaptcha) {
        withInterceptor()
      } else {
        handleLogin()
      }
    })
    .catch(() => {
      withInterceptor()
    })
}
</script>
<style lang="less" scoped>
.sign-in {
  width: 100%;
  height: 100%;
  background: url('@/assets/images/login-bg.png') no-repeat;
  background-size: cover;
}
:deep(.sign-form) {
  position: absolute;
  left: 15%;
  top: 50%;
  border-radius: 0.75rem;
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
  padding: 56px;
  font-size: 0.875rem;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
  width: 480px;
  min-height: 396px;
  background-color: #fff;
  box-shadow: 0.125rem 0.125rem 3.125rem 0 rgba(58, 58, 58, 0.04);
  .arco-input {
    height: 48px;
  }
  .arco-btn {
    height: 48px;
    margin-top: 24px;
  }
}
</style>
